import type { InputInstance } from "element-plus";

import { defineStore } from "pinia";
import { useArticleStore } from "./article";
import { TextStyleModifier } from "@/views/annotation/textStyleModifier";
import { selectedText, hoverBarRef } from "@/views/annotation/state";

interface Note {
  id: string;
  note: string;
  noteWidth: number;
  noteHeight: number;
}
type NoteStatus = "update" | "add";
const articleStore = useArticleStore();

export const useNoteStore = defineStore("note", () => {
  let noteStatus: NoteStatus = "add";
  const isShowedNote = ref(false);
  const noteEditorRef = ref<InputInstance>();
  const rangeAxis = reactive({
    startX: 0,
    startY: 0,
    endX: 0,
    endY: 0,
  });
  const notePosition = reactive({
    x: 0,
    y: 0,
  });
  const currentNote = ref<Note>({
    id: "",
    note: "",
    noteWidth: 0,
    noteHeight: 0,
  });

  const getCurrentNote = computed(() => {
    return currentNote.value;
  });

  const changeCurrentNote = (styleId: string) => {
    if (currentNote.value.id === styleId) return;
    const currentStyle = articleStore.getCurrentArticle!.styles![styleId];
    const isNoteType = "note" in currentStyle;
    if (isNoteType) {
      currentNote.value = { ...(currentStyle as Note), id: styleId };
      noteStatus = "update";
    }
  };

  const getNoteStatus = (): NoteStatus => noteStatus;

  function _initNoteStyle() {
    const halfWidth = ElementUtils.getElementHalfWidth(
      ".note-editor-container"
    )!;

    notePosition.x =
      rangeAxis.endX - (rangeAxis.endX - rangeAxis.startX) / 2 - halfWidth;

    notePosition.y = Math.max(rangeAxis.startY, rangeAxis.endY) + 10;
    const { style } = noteEditorRef.value?.textarea!;
    style.width = "200px";
    style.height = "100px";
  }

  function _setNoteWidthAndHeight() {
    const { clientWidth, clientHeight } = getElementProps(
      ".el-textarea__inner",
      ["clientWidth", "clientHeight"]
    );
    const article = articleStore.getCurrentArticle!;

    articleStore.updateArticleStyle(article.id, currentNote.value.id, {
      noteWidth: +clientWidth,
      noteHeight: +clientHeight,
    });
  }

  function _updateNoteContent() {
    const article = articleStore.getCurrentArticle!;
    articleStore.updateArticleStyle(article.id, currentNote.value.id, {
      note: currentNote.value.note,
    });
  }

  function _addNote() {
    const article = articleStore.getCurrentArticle!;
    const { uuid, changedContent } =
      TextStyleModifier.modifySelectedTextRangeStyle(
        selectedText.value,
        "note"
      );
    articleStore.updateArticleHtmlContent(article.id, changedContent);
    articleStore.updateArticle(article.id, {
      ...article,
      htmlContent: changedContent,
    });
    currentNote.value.id = uuid;
  }

  function _clearNote() {
    currentNote.value = {
      id: "",
      note: "",
      noteWidth: 0,
      noteHeight: 0,
    };
  }

  function closeNote() {
    isShowedNote.value = false;

    if (!currentNote.value.note) return;
    if (getNoteStatus() === "add") _addNote();
    _updateNoteContent();
    _setNoteWidthAndHeight();
    _clearNote();
  }

  function handleNoteFun() {
    noteStatus = "add";
    _clearNote();
    isShowedNote.value = true;
    nextTick(() => {
      noteEditorRef.value!.focus();
      _initNoteStyle();
      // articleStore.removeNoExistIdFromStyles();
    });
  }

  function shouldShowNote(target: Element) {
    const isWrongNode = target.nodeName === "DIV";
    const isShowedHoverBar = hoverBarRef.value!.getVisible();
    const shouldNotShow = isWrongNode || isShowedNote.value || isShowedHoverBar;
    const hasNote = articleStore.getCurrentArticle!.styles?.[target.id]?.note;
    return !shouldNotShow && hasNote;
  }

  interface Axis {
    x: number;
    y: number;
  }

  function _handleNoteEditorStyle(id: string, axis: Axis) {
    const noteItem = articleStore.getCurrentArticle!.styles?.[id]!;
    const halfWidth = ElementUtils.getElementHalfWidth(
      ".note-editor-container"
    )!;
    notePosition.x = axis.x - halfWidth;
    notePosition.y = axis.y;
    const { style } = noteEditorRef.value!.textarea!;
    style.width = noteItem.noteWidth + "px";
    style.height = noteItem.noteHeight + "px";
  }

  function showNote(styleId: string, axis: Axis) {
    isShowedNote.value = true;
    nextTick(() => {
      _handleNoteEditorStyle(styleId, axis);
    });
  }

  return {
    getCurrentNote,
    changeCurrentNote,
    getNoteStatus,
    rangeAxis,
    notePosition,
    noteEditorRef,
    handleNoteFun,
    closeNote,
    showNote,
    isShowedNote,
    shouldShowNote,
  };
});
